using MyBlogServer.Data;
using MyBlogServer.Models;
using Dapper;
using Microsoft.Data.Sqlite;
using System.Security.Cryptography;
using System.Text;

namespace MyBlogServer.Services
{
    public class UserService
    {
        private readonly BlogContext _context;

        public UserService(BlogContext context)
        {
            _context = context;
        }

        public User? Authenticate(string username, string password)
        {
            using var connection = _context.CreateConnection() as SqliteConnection;
            connection!.Open();
            var sql = "SELECT * FROM Users WHERE Username = @Username";
            var user = connection.QueryFirstOrDefault<User>(sql, new { Username = username });
            
            Console.WriteLine($"查找用户: {username}, 找到: {user != null}");

            if (user != null && VerifyPassword(password, user.PasswordHash))
            {
                return user;
            }

            return null;
        }

        public async Task<User?> AuthenticateAsync(string username, string password)
        {
            Console.WriteLine($"=== AuthenticateAsync 开始 ===");
            Console.WriteLine($"收到认证请求: 用户名='{username}', 密码长度={password.Length}");
            Console.WriteLine($"用户名详细信息: 长度={username.Length}, 字节=[{string.Join(",", System.Text.Encoding.UTF8.GetBytes(username))}]");
            Console.WriteLine($"密码详细信息: 长度={password.Length}, 字节前几位=[{string.Join(",", System.Text.Encoding.UTF8.GetBytes(password).Take(10))}{(password.Length > 10 ? "..." : "")}]");
            
            // 检查参数是否为空或空白
            if (string.IsNullOrWhiteSpace(username))
            {
                Console.WriteLine("警告: 用户名为空或空白");
                Console.WriteLine($"=== AuthenticateAsync 结束 (用户名为空) ===");
                return null;
            }
            
            if (string.IsNullOrEmpty(password))
            {
                Console.WriteLine("警告: 密码为空");
                Console.WriteLine($"=== AuthenticateAsync 结束 (密码为空) ===");
                return null;
            }
            
            Console.WriteLine($"开始认证用户: '{username}'，密码长度: {password.Length}");
            
            using var connection = _context.CreateConnection() as SqliteConnection;
            connection!.Open();
            var sql = "SELECT * FROM Users WHERE Username = @Username";
            var user = await connection.QueryFirstOrDefaultAsync<User>(sql, new { Username = username });
            
            Console.WriteLine($"查找用户: '{username}', 找到: {user != null}");
            
            if (user != null)
            {
                Console.WriteLine($"数据库中的用户: {user.Username}, 密码哈希: {user.PasswordHash}");
            }

            if (user != null && VerifyPassword(password, user.PasswordHash))
            {
                Console.WriteLine("密码验证成功");
                Console.WriteLine($"=== AuthenticateAsync 结束 (成功) ===");
                return user;
            }
            
            Console.WriteLine("用户不存在或密码错误");
            Console.WriteLine($"=== AuthenticateAsync 结束 (验证失败) ===");

            return null;
        }
        
        public async Task<bool> ChangePasswordAsync(string username, string currentPassword, string newPassword)
        {
            // 首先验证当前密码
            var user = await AuthenticateAsync(username, currentPassword);
            if (user == null)
            {
                return false;
            }
            
            // 更新密码
            using var connection = _context.CreateConnection() as SqliteConnection;
            connection!.Open();
            var sql = "UPDATE Users SET PasswordHash = @PasswordHash WHERE Username = @Username";
            var affectedRows = await connection.ExecuteAsync(sql, new { 
                PasswordHash = HashPassword(newPassword), 
                Username = username 
            });
            
            return affectedRows > 0;
        }

        private string HashPassword(string password)
        {
            using var sha256 = SHA256.Create();
            var hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password));
            var hash = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
            Console.WriteLine($"计算密码哈希: 输入密码='{password}', 哈希={hash}");
            return hash;
        }

        private bool VerifyPassword(string password, string hash)
        {
            var hashedPassword = HashPassword(password);
            Console.WriteLine($"验证密码: 输入密码='{password}', 计算哈希={hashedPassword}, 存储哈希={hash}, 匹配={hashedPassword == hash}");
            return hashedPassword == hash;
        }
    }
}